from tkinter import filedialog, Tk, Label, Scale, Button, messagebox
from PIL import Image, ImageDraw, ImageTk
import os
import tkinter
from tkinter import LabelFrame

class rua():
    def __init__(self, img_file):
        self.author = Image.open(img_file)

    def add_png(self, png_d, scale=1.0):  # 添加scale参数控制缩放
        # 计算缩放后的尺寸
        width = int(png_d[0] * scale)
        height = int((png_d[1] - png_d[2]) * scale)
        author = self.author.resize((width, height))

        # 载入素材
        rua_p1 = Image.open(png_d[3])

        # 创建背景模板
        rua_png1 = Image.new('RGBA', (110, 110), (255, 255, 255, 255))

        # 使用预定义的参数：jd，合成一帧的样例
        rua_png1.paste(author, (110 - png_d[0], 110 - png_d[1] + png_d[2]), author)
        rua_png1.paste(rua_p1, (0, 110 - png_d[1] - png_d[2]), rua_p1)
        return rua_png1

    def add_gif(self, target_size=90):  # 添加target_size参数，默认值90
        # 获取data文件夹路径（使用pkg_resources处理打包后的资源）
        try:
            import pkg_resources
            png_dir = pkg_resources.resource_filename(__name__, 'data')
        except:
            png_dir = os.path.join(os.path.dirname(__file__), 'data')
        
        if not os.path.exists(png_dir):
            raise FileNotFoundError(f"找不到data文件夹: {png_dir}")
            
        # 获取素材列表
        pst = os.listdir(png_dir)
        for i in range(len(pst)):
            pst[i] = os.path.join(png_dir, pst[i])  # 使用os.path.join处理路径

        # 预调试好的参数，传入素材列表
        jd = [
            [90, 90, 5, pst[0]],
            [90, 87, 5, pst[2]],
            [90, 84, 10, pst[3]],
            [90, 81, 8, pst[4]],
            [90, 78, 5, pst[5]],
            [90, 75, 5, pst[6]],
            [90, 72, 8, pst[7]],
            [90, 74, 8, pst[8]],
            [90, 77, 9, pst[9]],
            [90, 80, 8, pst[1]]
        ]
        
        # 重置要生成的图片大小（使用传入的尺寸参数）
        self.author = self.author.resize((target_size, target_size))

        # 绘制模板（保持原尺寸不变）
        alpha_layer = Image.new('L', (90, 90), 0)
        draw = ImageDraw.Draw(alpha_layer)
        draw.ellipse((0, 0, 90, 90), fill=255)
        self.author.putalpha(alpha_layer)

        # gif列表
        gifs = []
        for i in range(len(jd)):
            # 将参数传递给生成方法
            # 添加到gif列表
            gifs.append(self.add_png(jd[i]))

        # 文件名,是否保存所有,图片列表,fps/ms
        gifs[0].save("dem.gif", "GIF", save_all=True, append_images=gifs, duration=35, loop=0)
        self.author.close()
        return "dem.gif"  # 新增返回GIF文件路径

    def show_gif(self, gif_path):
        """显示生成的GIF动画"""
        root = tkinter.Tk()
        root.title("GIF预览")
        
        # 加载GIF
        gif = Image.open(gif_path)
        frames = []
        try:
            while True:
                frames.append(ImageTk.PhotoImage(gif.copy()))
                gif.seek(gif.tell() + 1)
        except EOFError:
            pass
        
        # 创建标签显示动画
        label = Label(root)
        label.pack()
        
        def update_frame(idx=0):
            label.config(image=frames[idx])
            root.after(35, update_frame, (idx + 1) % len(frames))
        
        update_frame()
        root.mainloop()


def main():
    # 创建主窗口
    root = Tk()
    root.title("GIF生成器")
    root.geometry("600x500")
    
    # 预览区域
    preview_frame = LabelFrame(root, text="预览", padx=10, pady=10)
    preview_frame.pack(pady=10)
    
    preview_label = Label(preview_frame)
    preview_label.pack()
    
    # 控制面板
    control_frame = tkinter.Frame(root)
    control_frame.pack(pady=10)
    
    # 缩放调整滑块
    size_frame = LabelFrame(control_frame, text="图片缩放")
    size_frame.grid(row=0, column=0, padx=10)
    
    size_slider = Scale(size_frame, from_=50, to=200, orient="horizontal")
    size_slider.set(90)
    size_slider.pack(padx=10, pady=5)
    
    # 速度调整滑块
    speed_frame = LabelFrame(control_frame, text="播放速度(ms)")
    speed_frame.grid(row=0, column=1, padx=10)
    
    speed_slider = Scale(speed_frame, from_=20, to=200, orient="horizontal")
    speed_slider.set(35)
    speed_slider.pack(padx=10, pady=5)
    
    # 按钮面板
    button_frame = tkinter.Frame(root)
    button_frame.pack(pady=10)
    
    # 全局变量
    current_frames = []
    current_speed = 35
    animation_id = None
    current_gif_path = None
    
    def update_animation(idx=0):
        nonlocal animation_id
        if current_frames:
            preview_label.config(image=current_frames[idx])
            animation_id = root.after(int(current_speed), update_animation, (idx + 1) % len(current_frames))
    
    def stop_animation():
        nonlocal animation_id
        if animation_id:
            root.after_cancel(animation_id)
            animation_id = None

    def export_gif():
        if not current_gif_path:
            messagebox.showwarning("警告", "请先生成GIF")
            return
        save_path = filedialog.asksaveasfilename(
            defaultextension=".gif",
            filetypes=[("GIF文件", "*.gif")]
        )
        if save_path:
            try:
                with open(current_gif_path, 'rb') as src, open(save_path, 'wb') as dst:
                    dst.write(src.read())
                messagebox.showinfo("成功", "GIF导出成功")
            except Exception as e:
                messagebox.showerror("错误", f"导出失败: {str(e)}")

    # 全局变量添加
    current_original_image = None
    current_gif_frames = []
    current_scale = 1.0

    def update_preview():
        nonlocal current_frames, animation_id
        stop_animation()
        if not current_gif_frames:
            return
            
        try:
            # 获取当前缩放比例
            current_scale = size_slider.get() / 90.0  # 90是默认值
            
            # 重新缩放预览帧
            frames = []
            for frame in current_gif_frames:
                img = frame.copy()
                img = img.resize((
                    int(img.width * current_scale),
                    int(img.height * current_scale)
                ))
                frames.append(ImageTk.PhotoImage(img))
                
            current_frames = frames
            if current_frames:
                update_animation()
                
        except Exception as e:
            messagebox.showerror("错误", f"更新预览失败: {str(e)}")

    def select_file():
        nonlocal current_frames, current_speed, animation_id, current_gif_path, current_original_image, current_gif_frames
        stop_animation()
        current_frames = []
        
        file_path = filedialog.askopenfilename()
        if not file_path:
            return
            
        try:
            current_speed = speed_slider.get()
            current_original_image = Image.open(file_path)
            
            # 生成GIF（使用默认尺寸）
            generator = rua(file_path)
            current_gif_path = generator.add_gif()
            
            # 加载并保存原始GIF帧
            gif = Image.open(current_gif_path)
            current_gif_frames = []
            try:
                while True:
                    current_gif_frames.append(gif.copy())
                    gif.seek(gif.tell() + 1)
            except EOFError:
                pass
                
            update_preview()  # 初始预览
                
        except Exception as e:
            messagebox.showerror("错误", f"生成GIF失败: {str(e)}")

    def on_size_change(event):
        if current_gif_frames:  # 如果有已生成的GIF帧
            update_preview()  # 直接更新预览

    # 将on_speed_change函数定义移到前面
    def on_speed_change(event):
        nonlocal current_speed
        current_speed = speed_slider.get()
        if animation_id:
            stop_animation()
            update_animation()
    
    # 然后再绑定事件
    size_slider.bind("<ButtonRelease-1>", on_size_change)
    speed_slider.bind("<ButtonRelease-1>", on_speed_change)
    
    # 按钮
    select_btn = Button(button_frame, text="选择图片", command=select_file)
    select_btn.grid(row=0, column=0, padx=10)
    
    export_btn = Button(button_frame, text="导出GIF", command=export_gif)
    export_btn.grid(row=0, column=1, padx=10)
    
    root.mainloop()

if __name__ == "__main__":
    main()
